home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / programming / mui / mcc_tipofday / mcc_tipofday_src / tip_converter.c < prev    next >
C/C++ Source or Header  |  1999-11-30  |  10KB  |  470 lines

  1.  
  2. /*
  3. ** $Id: tip_converter.c,v 1.4 1999/11/20 13:34:54 carlos Exp $
  4. **
  5. **       © 1999 Marcin Orlowski <carlos@amiga.com.pl>
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11.  
  12. #include <dos/dos.h>
  13. #include <dos/dostags.h>
  14. #include <libraries/iffparse.h>
  15. #include <clib/utility_protos.h>
  16.  
  17. #include <proto/dos.h>
  18. #include <proto/iffparse.h>
  19. #include <proto/exec.h>
  20.  
  21. #include "tip_converter_revision.h"
  22.  
  23. #define ID_VERS    MAKE_ID('V','E','R','S')
  24. #define ID_TIPS    MAKE_ID('T','I','P','S')     // Tips file
  25. #define ID_TIPC    MAKE_ID('M','A','X',' ')     // Tips count
  26. #define ID_LAST    MAKE_ID('L','A','S','T')     // last shown tip
  27. #define ID_SHOW    MAKE_ID('S','H','O','W')     // show on startup
  28.  
  29. #define TIP_LEN 512
  30.  
  31.  
  32. struct BaseVersion
  33. {
  34.   UWORD Version;
  35.   UWORD Revision;
  36. };
  37.  
  38.  
  39. struct TipList
  40. {
  41.     struct MinNode tl_node;
  42.     char   Tip[ TIP_LEN ];
  43. };
  44.  
  45. struct List tips;
  46.  
  47. /// FreeTips
  48. void FreeTips( void )
  49. {
  50.  
  51. struct TipList *tip, *tip_next;
  52.  
  53.     if( !IsListEmpty(&tips) )
  54.        {
  55.        for(tip = (struct TipList *)tips.lh_Head; tip->tl_node.mln_Succ; )
  56.            {
  57.            Remove( (struct Node*)tip );
  58.            tip_next = (struct TipList *)tip->tl_node.mln_Succ;
  59.            free( tip );
  60.            tip = tip_next;
  61.            }
  62.        }
  63. }
  64. //|
  65. /// AddTip
  66.  
  67. char AddTip( char *tip )
  68. {
  69.  
  70. struct TipList *nowy = calloc(1, sizeof(struct TipList) );
  71.  
  72.     if( nowy )
  73.        {
  74.        memcpy( &nowy->Tip, tip, TIP_LEN );
  75.        AddTail( &tips, (struct Node *)nowy );
  76.        }
  77.  
  78.     return(0);
  79. }
  80.  
  81. //|
  82. /// StrToLower
  83.  
  84. void strtolower( char *dest_buffer, char * src )
  85. {
  86.     for(; *src;)
  87.        {
  88.        *dest_buffer = ToLower(*src);
  89.        src++;
  90.        dest_buffer++;
  91.        }
  92.     *dest_buffer=0;
  93. }
  94. //|
  95.  
  96. // the following functions are taken
  97. // as-is from the FlexCat source code
  98.  
  99. #define tolower         ToLower
  100.  
  101. /// FUNC: MemError
  102.  
  103. /*
  104.     This shows the message: Memory error.
  105. */
  106. void MemError(void)
  107. {
  108.   fprintf(stderr, "ERROR: Not enough memory!\n");
  109. }
  110. //|
  111. /// FUNC: getoctal
  112.  
  113. /*
  114.     This translates an octal digit.
  115. */
  116. int getoctal(int c)
  117. {
  118.  
  119.   if (c >= '0'  &&  c <= '7')
  120.     {
  121.     return(c - '0');
  122.     }
  123.  
  124.   fprintf(stderr, "WARN: Expected Octal numer\n");
  125.   return(0);
  126.  
  127. }
  128. //|
  129. /// FUNC: gethex
  130. /*
  131.     This translates a hex character.
  132. */
  133. int gethex(int c)
  134. {
  135.   if (c >= '0'  &&  c <= '9')
  136.   { return(c - '0');
  137.   }
  138.   else if (c >= 'a'  &&  c <= 'f')
  139.   { return(c - 'a' + 10);
  140.   }
  141.   else if (c >= 'A'  &&  c <= 'F')
  142.   { return(c - 'A' + 10);
  143.   }
  144.  
  145.   fprintf(stderr, "WARN: Expected Hex number\n");
  146.   return(0);
  147. }
  148. //|
  149. /// FUNC: ReadChar
  150.  
  151. /*
  152.     ReadChar scans an input line translating the backslash characters.
  153.  
  154.     Inputs: strptr  - a pointer to a stringpointer; the latter points to the
  155.                       next character to be read and points behind the read
  156.                       bytes after executing ReadChar
  157.             dest    - a pointer to a buffer, where the read bytes should be
  158.                       stored
  159.  
  160.     Result: number of bytes that are written to dest (between 0 and 2)
  161. */
  162. int ReadChar(char **strptr, char *dest)
  163. {
  164.   char c;
  165.   int i;
  166.  
  167.   switch(c = *((*strptr)++))
  168.     {
  169.     case '\\':
  170.  
  171.       switch(c = tolower((int) *((*strptr)++)))
  172.         {
  173.         case '\n':
  174.           return(0);
  175.         case 'b':
  176.           *dest = '\b';
  177.           break;
  178.         case 'c':
  179.           *dest = '\233';
  180.           break;
  181.         case 'e':
  182.           *dest = '\033';
  183.           break;
  184.         case 'f':
  185.           *dest = '\f';
  186.           break;
  187.         case 'g':
  188.           *dest = '\007';
  189.           break;
  190.         case 'n':
  191.           *dest = '\n';
  192.           break;
  193.         case 'r':
  194.           *dest = '\r';
  195.           break;
  196.         case 't':
  197.           *dest = '\t';
  198.           break;
  199.         case 'v':
  200.           *dest = '\013';
  201.           break;
  202.         case 'x':
  203.           *dest = gethex((int) **strptr);
  204.           (*strptr)++;
  205.           if (((c = **strptr) >= '0'  &&  c <= '9')  ||
  206.               (c >= 'a'  &&  c <= 'f')  ||  (c >= 'A'  &&  c <= 'F'))
  207.           { *dest = (*dest << 4) + gethex((int) c);
  208.             (*strptr)++;
  209.           }
  210.           break;
  211.         case '0':
  212.         case '1':
  213.         case '2':
  214.         case '3':
  215.         case '4':
  216.         case '5':
  217.         case '6':
  218.         case '7':
  219.  
  220.           *dest = getoctal((int)c);
  221.  
  222.           for(i = 0;  i < 2;  i++)
  223.             {
  224.             if((c = **strptr) >= '0'  &&  c <= '7')
  225.               {
  226.               *dest = (*dest << 3) + getoctal((int) c);
  227.               (*strptr)++;
  228.               }
  229.             }
  230.           break;
  231.         case ')':
  232.         case '\\':
  233.           *(dest++) = '\\';
  234.           *dest = c;
  235.           return(2);
  236.         default:
  237.           *dest = c;
  238.       }
  239.       break;
  240.  
  241.     default:
  242.       *dest = c;
  243.   }
  244.   return(1);
  245. }
  246. //|
  247.  
  248. // end of rip-offs
  249.  
  250. /// main
  251. void main( int argc, char **argv)
  252. {
  253. char   outname[256];
  254. BPTR   in = NULL;
  255.  
  256. ULONG  count    = 0;
  257. ULONG  empty    = 0;
  258. ULONG  comments = 0;
  259.  
  260. char   quiet = FALSE;
  261.  
  262.  
  263.     NewList( &tips );
  264.  
  265.  
  266.  
  267.     if( argc < 2 || argc > 4 )
  268.        {
  269.        printf("ASCII->Tips converter " __AMIGADATE__ "\n");
  270.        fprintf(stderr, "Usage: %s infile outfile [QUIET]\n", argv[0]);
  271.        exit(20);
  272.        }
  273.  
  274.  
  275.     quiet = ( argc == 4 );
  276.  
  277.     if( !quiet )
  278.         printf("ASCII->Tips converter " __AMIGADATE__ "\n");
  279.  
  280.  
  281.     // reading source file...
  282.  
  283.     if( in = Open( argv[1], MODE_OLDFILE ) )
  284.       {
  285.       char   buffer[ 2*TIP_LEN ];
  286.       char   buffer_tmp[ TIP_LEN ];
  287.  
  288.       if( !quiet )
  289.         printf( "Reading '%s'...\n", argv[1] );
  290.  
  291.  
  292.       // read loop
  293.  
  294.       while( FGets( in, buffer, sizeof( buffer ) ) )
  295.         {
  296.         int len = strlen( buffer );
  297.  
  298.         if( len > 0 )
  299.            {
  300.            if( (len != 1) && buffer[0] != 10 )
  301.              {
  302.              char *p = strchr( buffer, '\n' );
  303.              if( p )
  304.                *p = 0;
  305.  
  306.              if( buffer[0] != ';' )
  307.                {
  308.                char *tmp_ptr = buffer;
  309.                char *dest    = buffer_tmp;
  310.  
  311.                while( *tmp_ptr )
  312.                  dest += ReadChar( &tmp_ptr, dest );
  313.  
  314.                *dest = 0;
  315.  
  316.  
  317.                AddTip( buffer_tmp );
  318.  
  319.                count++;
  320.                }
  321.              else
  322.                {
  323.                comments++;
  324.                }
  325.              }
  326.            else
  327.              {
  328.              empty++;
  329.              }
  330.            }
  331.         else
  332.            {
  333.            empty++;
  334.            }
  335.         }
  336.  
  337.       Close( in );
  338.  
  339.       if( !quiet )
  340.          printf("  %ld tips read. %ld comments, %ld empty lines skipped\n", count, comments, empty );
  341.       }
  342.     else
  343.       {
  344.       fprintf(stderr,  "** Can't open input file '%s'\n", argv[1] );
  345.       exit( 20 );
  346.       }
  347.  
  348.  
  349.  
  350.  
  351.  
  352.     // saving...
  353.        {
  354.        struct IFFHandle *MyIFFHandle = NULL;
  355.        int len = strlen( argv[2] );
  356.  
  357.        strcpy( outname, argv[2] );
  358.  
  359.  
  360.        if( len > 4 )
  361.            if( stricmp( ".tips", &argv[2][len-5] ))
  362.               strcat( outname, ".tips" );
  363.  
  364.  
  365.  
  366.        if( MyIFFHandle = AllocIFF() )
  367.          {
  368.          BPTR  FileHandle;
  369.  
  370.          if( FileHandle = Open( outname, MODE_NEWFILE ) )
  371.            {
  372.            MyIFFHandle->iff_Stream = FileHandle;
  373.            InitIFFasDOS( MyIFFHandle );
  374.  
  375.            if(OpenIFF( MyIFFHandle, IFFF_WRITE ) == 0)
  376.                {
  377.                struct TipList *node;
  378.                struct BaseVersion version;
  379.  
  380.                if( !quiet )
  381.                    printf( "Saving '%s'...\n", outname );
  382.  
  383.                PushChunk(MyIFFHandle, ID_TIPS, ID_CAT, IFFSIZE_UNKNOWN);
  384.  
  385.                // version string
  386.                PushChunk(MyIFFHandle, ID_TIPS, ID_FORM, IFFSIZE_UNKNOWN);
  387.                    PushChunk(MyIFFHandle, ID_TIPS, ID_VERS, IFFSIZE_UNKNOWN);
  388.                    version.Version  = VERSION;
  389.                    version.Revision = REVISION;
  390.                    WriteChunkBytes( MyIFFHandle, &version, sizeof(version) );
  391.                    PopChunk(MyIFFHandle);
  392.  
  393. /*
  394.                    PushChunk(MyIFFHandle, ID_TIPS, ID_ANNO, IFFSIZE_UNKNOWN);
  395.                    WriteChunkBytes( MyIFFHandle, anno, strlen(anno) );
  396.                    PopChunk(MyIFFHandle);
  397. */
  398.  
  399.                PopChunk(MyIFFHandle);
  400.  
  401.  
  402.                // header...
  403.  
  404.                PushChunk(MyIFFHandle, ID_TIPS, ID_FORM, IFFSIZE_UNKNOWN);
  405.                    PushChunk(MyIFFHandle, ID_TIPS, ID_TIPC, IFFSIZE_UNKNOWN);
  406.                    WriteChunkBytes( MyIFFHandle, &count, sizeof(ULONG) );
  407.                    PopChunk(MyIFFHandle);
  408.                PopChunk(MyIFFHandle);
  409.  
  410.                // Tips...
  411.                PushChunk(MyIFFHandle, ID_TIPS, ID_FORM, IFFSIZE_UNKNOWN);
  412.  
  413.                {
  414.                ULONG index = 0;
  415.  
  416.                for(node = (struct TipList *)tips.lh_Head; node->tl_node.mln_Succ; node = (struct TipList *)node->tl_node.mln_Succ)
  417.                    {
  418.                    // saving entry...
  419.                    char _id[5];
  420.                    ULONG IFF_ID;
  421.  
  422.                    sprintf( _id, "%04lx", index );
  423.                    strtolower( _id, _id );
  424.                    IFF_ID = MAKE_ID( _id[0], _id[1], _id[2], _id[3] );
  425.  
  426.                    PushChunk( MyIFFHandle, ID_TIPS, IFF_ID, IFFSIZE_UNKNOWN );
  427.                    WriteChunkBytes( MyIFFHandle, node->Tip, strlen( node->Tip) );
  428.                    PopChunk( MyIFFHandle );
  429.  
  430.                    index++;
  431.                    }
  432.                }
  433.                PopChunk(MyIFFHandle);
  434.  
  435.                // pop CAT
  436.                PopChunk(MyIFFHandle);
  437.                CloseIFF(MyIFFHandle);
  438.                }
  439.            else
  440.                {
  441.                fprintf(stderr,  "** Can't OpenIFF() for '%s'\n", outname );
  442.                }
  443.  
  444.            Close(FileHandle);
  445.            }
  446.         else
  447.            {
  448.            fprintf(stderr, "** Can't open \"%s\" for write\n", outname );
  449.            }
  450.  
  451.         FreeIFF(MyIFFHandle);
  452.         }
  453.      else
  454.         {
  455.         fprintf(stderr, "** Can't AllocIFF()\n");
  456.         exit(20);
  457.         }
  458.  
  459.     }
  460.  
  461.  
  462.     FreeTips();
  463.  
  464.     if( !quiet )
  465.         printf("Done.\n");
  466.  
  467. }
  468. //|
  469.  
  470.